# 1.初始化列表
import json

class Table:
    components = []

    # table 头配置
    def __init__(self, config):
        if 'table' not in config:
            raise Exception('package.json文件缺少table字段')

        # 搜索配置
        self.toolbar_cfg = config['toolbar']

        # 表格配置
        self.table_cfg = config['table']


    def tpl_toolbar(self):
        tpl = f'''
        <div class="toolbar">
            {self.tpl_toolbar_actions()}
            {self.tpl_toolbar_search()}
        </div>
        '''
        return tpl

    def tpl_toolbar_actions(self):
        actions = self.toolbar_cfg['actions']
        tpl = ''
        for action in actions:
            if 'component' in action:
                # 如果存在component，则添加到components中
                component = {
                    'name': action['component'],
                    'method': action['action'],
                    'params': '',
                }
                self.components.append(component)

            tpl += f'''<el-button type="{action['type']}" @click="{action['action']}">{action['label']}</el-button>'''
        return tpl

    # 生成搜索项
    def tpl_search_items(self):
        items = self.toolbar_cfg['search']

        tpl = ''
        for item in items:
            if item['type'] == 'text':
                tpl += f'''
                <el-form-item label="{item['label']}">
                    <el-input v-model="searchForm.{item['name']}"></el-input>
                </el-form-item>
                '''
            elif item['type'] == 'select':
                tpl += f'''
                <el-form-item label="{item['label']}">
                    <el-select v-model="searchForm.{item['name']}">
                        <el-option v-for="item in {item['options']}" :key="item.value" :label="item.label" :value="item.value"></el-option>
                    </el-select>
                </el-form-item>
                '''
            elif item['type'] == 'date':
                tpl += f'''
                <el-form-item label="{item['label']}">
                    <el-date-picker v-model="searchForm.{item['name']}" type="date" data-value="YYYY-MM-DD" placeholder="选择日期"></el-date-picker>
                </el-form-item>
                '''
        return tpl

    def tpl_toolbar_search(self):
        tpl = f'''
        <el-form :inline="true" :model="searchForm" class="demo-form-inline">
            {self.tpl_search_items()}
            <el-form-item>
                <el-button type="primary" @click="handleSearch">查询</el-button>
            </el-form-item>
            <el-form-item>
                <el-button @click="resetSearch">重置</el-button>
            </el-form-item>
        </el-form>
        '''
        return tpl

    # 生成表格
    def tpl_table(self):
        tpl = f'''
        <el-table :data="tableData" style="width: 100%">
            {self.tpl_columns()}
        </el-table>
        '''
        return tpl

    def tpl_columns(self):
        # 是否可选
        multi_select = self.table_cfg['multiSelect']

        # 获取列的配置
        columns = self.table_cfg['columns']

        tpl = ''
        # 如果可选，添加选择列
        if multi_select:
            tpl += '''<el-table-column type="selection" width="55"></el-table-column>'''

        # 循环字段
        for column in columns:
            # width 如果没有配置，则不设置
            if 'width' in column:
                tpl += f'''<el-table-column prop="{column['prop']}" label="{column['label']}" width="{column['width']}"></el-table-column>'''
            else:
                tpl += f'''<el-table-column prop="{column['prop']}" label="{column['label']}"></el-table-column>'''

        # 操作列
        actions = self.table_cfg['actions']

        tpl += '''<el-table-column label="操作">
            <template #default="{row}">'''
        # 循环操作
        for action in actions:
            # 如果存在component，则添加到components中
            if 'component' in action:
                # 构造函数名及引用变量
                component = {
                    'name': action['component'],
                    'params': 'row'
                }
                self.components.append(component)


            tpl += f'''<el-button type="{action['type']}" size="mini" @click="{action['action']}(row)">{action['label']}</el-button>'''

        tpl += '''</template>
        </el-table-column>'''
        return tpl

    def tpl_components(self):
        tpl = ''
        for component in self.components:
            tpl += f'''<{component['name']} ref="{component['name']}Ref"></{component['name']}>\n'''

        return tpl

    def tpl_pagination(self):
        tpl = f'''
        <common-pagination :pagination="pagination" @fetch-list="getTableData"></common-pagination>
        '''
        return tpl

    def generate_tpl(self):
        tpl = f'''<template><el-main>'''
        tpl += self.tpl_toolbar()
        tpl += self.tpl_table()
        tpl += self.tpl_pagination()
        tpl += self.tpl_components()
        tpl += f'''</el-main></template>'''
        return tpl

    def code_imports(self):

        code = ''
        for component in self.components:
            name, params = component['name'], component['params']
            print(name, params)

            code += f'''import {name} from '@/components/{name}.vue'\n'''
            code += f'''const {name}Ref = ref(null)'''

            # 如果以dialog结尾，则添加打开dialog的函数
            if name.endswith('Dialog'):
                code += f'''
                const open{name} = ({params}) => {{
                    {name}Ref.value.openDialog()
                }}
                '''
            else:
                code += f'''
                const {name}Drawer = ({params}) => {{
                    {name}Ref.value.openDialog()
                }}
                '''

        return code

    def code_search(self):
        # 根据search配置生成searchForm
        search = self.toolbar_cfg['search']
        code = 'const searchForm = reactive({'
        for item in search:
            code += f'''{item['name']}: '','''
        code += '});'

        return code

    def code_table(self):
        # 根据table配置生成tableData
        config = self.table_cfg
        source = config['source']
        code = f'''import {source['method']} from '{source['api']}';\n'''
        code += 'const tableData = ref([]);'
        # 定义分页配置
        code += '''
        import CommonPagination from "@/components/pagination.vue";
        const pagination = ref({
            page: 1,
            size: 10,
            total: 0
        })'''

        # 定义获取tableData函数
        code += f'''
        const getTableData = () => {{
            let params = searchForm;
            params.pagination = pagination.value;
            {source['method']}(params).then(res => {{
                tableData.value = res.data
                pagination.value.total = res.pagination.total
            }})
        }}
        '''

        # 定义检索事件
        code += '''
        const handleSearch = () => {
            pagination.value.page = 1
            getTableData()
        }
        '''

        # 重置检索条件
        code += '''
        const handleReset = () => {
            getTableData()
        }
        '''

        # 设置默认加载函数
        code += '''
        onMounted(() => {
            getTableData()
        })
        '''

        return code

    def generate_code(self):
        code = '''<script setup>
        import { ref } from 'vue';
        import { ElMessage,ElMessageBox } from 'element-plus'
        '''
        code += self.code_imports()
        code += self.code_search()
        code += self.code_table()
        code += '''</script>'''

        return code

    # 执行
    def display(self):
        # 执行顺序是先生成模板，再生成代码
        tpl = self.generate_tpl()
        code = self.generate_code()
        # 将模板写入到src/components/table.vue文件中
        with open('src/components/Table.vue', 'w', encoding='utf-8') as f:
            f.write(code)
            f.write(tpl)


if __name__ == '__main__':
    # 打开配置文件 task/table.json

    with open('task/table.json', 'r') as f:
        cfg = json.load(f)

    if 'table' not in cfg:
        raise Exception('table.json文件缺少table字段')

    table = Table(cfg);
    table.display()
